package com.xiaoq.feature.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiaoq.ESIndexNameProperties;
import com.xiaoq.feature.entity.ShopFoodEntity;
import com.xiaoq.feature.entity.VegetRecomEntity;
import com.xiaoq.feature.repository.IShopFoodRepository;
import com.xiaoq.feature.repository.IVegetRecomRepository;
import com.xiaoq.feature.service.IShopFoodService;
import com.xiaoq.sites.vo.SearchResultVo;
import com.xiaoq.vo.PagingVo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class ShopFoodServiceImpl implements IShopFoodService {

	private Logger logger = LoggerFactory.getLogger(ShopFoodServiceImpl.class);

	@Autowired
	private IShopFoodRepository shopFoodRep;

	@Autowired
	private ElasticsearchTemplate template;

	@Autowired
	private ESIndexNameProperties indexNameProperties;

	private static final ObjectMapper MAPPER = new ObjectMapper();


	@Autowired
	private IVegetRecomRepository vegetRecomRep;
	
	@Override
	public boolean save(ShopFoodEntity shopFood) {
		return shopFoodRep.save(shopFood);
	}

	@Override
	public List<ShopFoodEntity> findShopFoodList(Double longitude, Double latitude,Double localLongitude,Double localLatitude, PagingVo pvo) {
		
		return shopFoodRep.findShopFoodList(longitude, latitude,localLongitude, localLatitude,pvo);
	}


	@Override
	public List<ShopFoodEntity> findShopFoodFromEsByText(String text, PagingVo pagingVo) {
		List<ShopFoodEntity> resultVos = new ArrayList<>();
		if(StringUtils.isBlank(text)){
			return resultVos;
		}

		Pageable pageable = new PageRequest(pagingVo.getPn(), pagingVo.getPs());
		QueryStringQueryBuilder builder=new QueryStringQueryBuilder(text).defaultField("cuisinesList.name");//.analyzer("ik_smart");
		SearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(builder)
				.withIndices(indexNameProperties.getSitesIndexName())
				.withTypes("shop_food")
				//.withHighlightFields(new HighlightBuilder.Field("cuisinesList.name").fragmentSize(500).numOfFragments(20).preTags("<font color = red>").postTags("</font>"))
				.withPageable(pageable)
				.build();

		template.queryForPage(searchQuery, ShopFoodEntity.class, new SearchResultMapper() {
			@Override
			public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
				SearchHit[] searchHits = response.getHits().getHits();

				if(searchHits==null || searchHits.length<1){
					return null;
				}

				for (SearchHit searchHit : response.getHits()) {
					String source = searchHit.getSourceAsString();
					ShopFoodEntity shopFoodEntity = null;
					try {
						shopFoodEntity = MAPPER.readValue(source, ShopFoodEntity.class);
						shopFoodEntity.setId(searchHit.getId());
						resultVos.add(shopFoodEntity);
					}catch (Exception e){
						logger.error(e.getMessage(), e);
					}
				}
				return null;
			}
		});

		return resultVos;
	}


	@Override
	public ShopFoodEntity findShopFood(String id) {
		return shopFoodRep.findShopFood(id);
	}


	@Override
	public List<ShopFoodEntity> findShopFoodList(Double longitude, Double latitude) {
		return shopFoodRep.findShopFoodList(longitude, latitude);
	}

	@Override
	public List<ShopFoodEntity> findShopFoodByVegetId(String vegetId) {
		VegetRecomEntity vegetRecom = vegetRecomRep.findVegetRecomById(vegetId);
		List<String> shoopFoodIds = vegetRecom.getShoopFoodIds();
		List<ShopFoodEntity> shopFoods = null;
		if(shoopFoodIds!= null){
			shopFoods = shopFoodRep.findShoopFoodListByIds(shoopFoodIds);
		}
		
		return shopFoods;
	}

	@Override
	public List<ShopFoodEntity> getShopFoodByPoint(double latitude, double longitude, long nearM, PagingVo pagingVo) {
		return shopFoodRep.getShopFoodByPoint(latitude, longitude, nearM, pagingVo);
	}

	@Override
	public List<ShopFoodEntity> getShopFoodFromEs(String name, PagingVo pagingVo) {
		return getShopFoodFromEs(name, pagingVo, null);
	}

	@Override
	public List<SearchResultVo> getShopFoodResultFromEs(String name, PagingVo pagingVo) {
		List<SearchResultVo> searchResultList = new ArrayList<>();
		getShopFoodFromEs(name, pagingVo, searchResultList);
		return searchResultList;
	}

	private List<ShopFoodEntity> getShopFoodFromEs(String name, PagingVo pagingVo, List<SearchResultVo> searchResultList){
		List<ShopFoodEntity> resultVos = new ArrayList<>();
		if(StringUtils.isBlank(name)){
			return resultVos;
		}

		boolean searchResultExist = (searchResultList != null);

		Pageable pageable = new PageRequest(pagingVo.getPn(), pagingVo.getPs());
		QueryStringQueryBuilder builder=new QueryStringQueryBuilder(name).defaultField("name");
		SearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(builder)
				.withIndices(indexNameProperties.getSitesIndexName())
				.withHighlightFields(new HighlightBuilder.Field("name").fragmentSize(500).numOfFragments(20).preTags("<span style=\"color:#ff9c05\">").postTags("</span>"))
				.withTypes("shop_food")
				.withPageable(pageable)
				.build();

		template.queryForPage(searchQuery, ShopFoodEntity.class, new SearchResultMapper() {
			@Override
			public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
				SearchHit[] searchHits = response.getHits().getHits();

				if(searchHits==null || searchHits.length<1){
					return null;
				}

				for (SearchHit searchHit : response.getHits()) {
					String source = searchHit.getSourceAsString();
					ShopFoodEntity shopFoodEntity;
					SearchResultVo searchResultVo;
					try {
						shopFoodEntity = MAPPER.readValue(source, ShopFoodEntity.class);
						shopFoodEntity.setId(searchHit.getId());

						if (searchResultExist) {
							searchResultVo = new SearchResultVo();

							searchResultVo.setLongitude(shopFoodEntity.getLongitude());
							searchResultVo.setLatitude(shopFoodEntity.getLatitude());
							searchResultVo.setId(shopFoodEntity.getId());
							searchResultVo.setType(70);
							searchResultVo.setContent(shopFoodEntity.getName());
							searchResultVo.setSourceTitle(shopFoodEntity.getName());
							searchResultVo.setZoneCity(shopFoodEntity.getZoneCity());
							searchResultVo.setHtmlTitle(searchHit.getHighlightFields().get("name").fragments()[0].toString());

							searchResultList.add(searchResultVo);
						}

						resultVos.add(shopFoodEntity);
					}catch (Exception e){
						logger.error(e.getMessage(), e);
					}
				}
				return null;
			}
		});

		return resultVos;
	}


	@Override
	public List<ShopFoodEntity> findShopFoodListByCity(String cityCode, PagingVo pvo) {
		return shopFoodRep.findShopFoodListByCity(cityCode, pvo);
	}

	@Override
	public boolean deleteShopFoodById(String shoptFoodId) {
		
		return shopFoodRep.deleteShopFoodById(shoptFoodId);
	}
}
